/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * principal.java
 *
 * Created on 30/09/2011, 10:49:42 AM
 */
package proyecto1ia;

import ag.cromosoma;
import java.awt.event.ActionEvent;
import javax.swing.JButton;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.io.FileWriter;
import java.io.PrintWriter;

/**
 *
 * @author jonathan
 */
public class principal extends javax.swing.JFrame {

    private int poblacion_inicial = 50;
    private int seleccion_padres = 0;
    private int tipo_cruce = 0;
    private int tipo_reemplazo;
    private int criterio_fin = 0; 
    private int generaciones = 10; 
    private int generacionesRecorridas;
    
    public int[][] matriz; //matriz donde se almancena el estado (-1:origen, -2:destino, 0:libre, 1:obstaculo)
    int[] pi = new int[2];
    int[] pf = new int[2];
    private JButton[][] boton;
    int SIZEX = 70;  //largo de cada boton
    int SIZEY = 70;  //alto de cada boton
    int cantx;
    int canty;
    
    boolean origen = false;
    boolean destino = false;
    boolean cargado = false;
    //datos de ejecucion
    String masCorto = "";
    String masLargo = "";
    int convergencia;
    long tiempo;
    /** Creates new form principal */
    public principal() {
        initComponents();
        if(!cargado)this.btnResolver.setEnabled(false);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        btnParametros = new javax.swing.JButton();
        btnDatosEjecucion = new javax.swing.JButton();
        jSeparator1 = new javax.swing.JSeparator();
        jPanel2 = new javax.swing.JPanel();
        btnCargarGrid = new javax.swing.JButton();
        jLabel2 = new javax.swing.JLabel();
        jLabel1 = new javax.swing.JLabel();
        btnResolver = new javax.swing.JButton();
        menuBar = new javax.swing.JMenuBar();
        fileMenu = new javax.swing.JMenu();
        exitMenuItem = new javax.swing.JMenuItem();
        helpMenu = new javax.swing.JMenu();
        contentsMenuItem = new javax.swing.JMenuItem();
        aboutMenuItem = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        btnParametros.setText("Parametros");
        btnParametros.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnParametrosActionPerformed(evt);
            }
        });

        btnDatosEjecucion.setText("Ver datos ejecucion");
        btnDatosEjecucion.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnDatosEjecucionActionPerformed(evt);
            }
        });

        jPanel2.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 306, Short.MAX_VALUE)
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 251, Short.MAX_VALUE)
        );

        btnCargarGrid.setBackground(javax.swing.UIManager.getDefaults().getColor("Button.shadow"));
        btnCargarGrid.setText("Cargar Grid");
        btnCargarGrid.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnCargarGridActionPerformed(evt);
            }
        });

        jLabel1.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        btnResolver.setText("Resolver");
        btnResolver.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnResolverActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 172, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                    .addComponent(btnParametros, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                    .addComponent(btnDatosEjecucion, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                                .addGap(47, 47, 47))))
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addGap(58, 58, 58)
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(btnResolver, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(btnCargarGrid, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
                .addGap(25, 25, 25))
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                    .addComponent(jLabel1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jLabel2, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 219, Short.MAX_VALUE))
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 19, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE))
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(btnParametros)
                .addGap(18, 18, 18)
                .addComponent(btnDatosEjecucion)
                .addGap(18, 18, 18)
                .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addComponent(btnCargarGrid)
                .addGap(54, 54, 54)
                .addComponent(btnResolver)
                .addContainerGap(64, Short.MAX_VALUE))
        );

        fileMenu.setMnemonic('f');
        fileMenu.setText("File");

        exitMenuItem.setMnemonic('x');
        exitMenuItem.setText("Exit");
        exitMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                exitMenuItemActionPerformed(evt);
            }
        });
        fileMenu.add(exitMenuItem);

        menuBar.add(fileMenu);

        helpMenu.setMnemonic('h');
        helpMenu.setText("Help");

        contentsMenuItem.setMnemonic('c');
        contentsMenuItem.setText("Contents");
        helpMenu.add(contentsMenuItem);

        aboutMenuItem.setMnemonic('a');
        aboutMenuItem.setText("About");
        helpMenu.add(aboutMenuItem);

        menuBar.add(helpMenu);

        setJMenuBar(menuBar);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void exitMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exitMenuItemActionPerformed
        System.exit(0);
    }//GEN-LAST:event_exitMenuItemActionPerformed

    private void btnParametrosActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnParametrosActionPerformed
        // TODO add your handling code here:
        ventana_parametros vp = new ventana_parametros();
        vp.setGeneraciones(this.generaciones);
        vp.setPoblacion_inicial(this.poblacion_inicial);
        vp.setCriterio(criterio_fin);
        vp.setPrincipal(this);
        vp.setVisible(true);
        
    }//GEN-LAST:event_btnParametrosActionPerformed

    private void btnDatosEjecucionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDatosEjecucionActionPerformed
        // TODO add your handling code here:
        ventanaDatos vd = new ventanaDatos();
        vd.setDatos(masLargo, masCorto, String.valueOf(convergencia), tiempo +" ms", String.valueOf(generacionesRecorridas));
        vd.setVisible(true);
    }//GEN-LAST:event_btnDatosEjecucionActionPerformed

    private void btnCargarGridActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCargarGridActionPerformed
        // TODO add your handling code here:       
        //this.jLabel2.setText("Alto:"+ this.jPanel2.getHeight() + " -Ancho:"+this.jPanel2.getWidth());
        cantx = Math.round(this.jPanel2.getWidth()/this.SIZEX);
        canty = Math.round(this.jPanel2.getHeight()/this.SIZEY);
        System.out.println("tam matriz:"+cantx + ","+canty);
        
        matriz = new int[cantx][canty];
        boton = new JButton[cantx][canty];
        this.jPanel2.setLayout(new GridLayout(cantx, canty));
        for (int i = 0; i < cantx; i++) {
            for (int j = 0; j < canty; j++) {
                matriz[i][j] = 0;
                boton[i][j] = new JButton();
                String nombre = new Integer(i).toString();
                nombre += new Integer(j).toString();
                boton[i][j].setActionCommand(nombre);
                boton[i][j].setVisible(true);
                boton[i][j].setName(i+","+j);
                boton[i][j].setBackground(Color.LIGHT_GRAY);
                //this.add(boton[i][j]);
                this.jPanel2.add(boton[i][j]);
            }
        }
        
        this.addListeners();
        this.jLabel1.setText("Click: coloca ORIGEN");
        this.btnCargarGrid.setEnabled(false);
//this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE );
//this.setSize(new Dimension(100,100));
    
    }//GEN-LAST:event_btnCargarGridActionPerformed

    private void btnResolverActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnResolverActionPerformed
        // TODO add your handling code here:
        //ag.genetica g = new ag.genetica(6); //pasarme manualmente el tamano del cromosoma
        tiempo = System.currentTimeMillis();
        int tam_cromosoma = cantx * canty;
        ag.genetica g = new ag.genetica(tam_cromosoma, pi, pf);
        g.setMatriz(matriz,cantx,canty);
        
        g.crear_poblacion_inicial(poblacion_inicial);
       // g.setFitnessRandom(); //solo para probar
       // g.evaluar_poblacion();        
        generacionesRecorridas = 0;
        
        for (int i = 0; i < this.generaciones; i++) {
            this.convergencia = g.getMasCorto().length();
            g.nuevaGeneracion();
            g.seleccion(seleccion_padres);
            g.setTipoCruce(tipo_cruce);
            g.evaluarPoblacion(); //evaluar poblacion resultante   
            generacionesRecorridas = i+1;
            if ((criterio_fin == 1) && (g.getSolucion().isSolucion())) { //terminar si hay solucion
                i = this.generaciones;                
            }   
            
        }       
       /* System.out.println("*********Padres********");
        g.seleccion(seleccion_padres);
        g.setTipoCruce(tipo_cruce);
        //g.cruce_uniforme();
        //g.show_poblacion_temporal();
        System.out.println("Inicia evaluacion *********");
        g.evaluarPoblacion(); //evaluar poblacion resultante
      */  
        cromosoma individuo = g.getSolucion();
        g.mostrarSolucion(individuo);
        System.out.println("Termino***********");
        int[][] ruta = g.getRuta(individuo);
        int tamano = individuo.getTamSolucion();
        this.pintarRuta(ruta, tamano);
        
        this.masCorto = g.getMasCorto();
        this.masLargo = g.getMasLargo();
        this.convergencia = masCorto.length() - convergencia;;
        
        tiempo = System.currentTimeMillis() - tiempo;
        
        g.guardarLog(masLargo, masCorto, String.valueOf(convergencia) , tiempo +" ms", String.valueOf(generacionesRecorridas));//setDatos(masLargo, masCorto, "22", tiempo +" ms", String.valueOf(generaciones))
        System.out.println("SOL:");
        
        
    }//GEN-LAST:event_btnResolverActionPerformed
    
    public void pintarRuta(int[][] ruta, int tamx) {
        limpiarRuta();
        int x, y;
        for(int i=0; i<tamx; i++){
            x=ruta[i][0];
            y=ruta[i][1];
            boton[x][y].setBackground(Color.green);
        }
    }
    
    public void limpiarRuta() {
        int estado;
        for (int i = 0; i < cantx; i++) {
            for (int j = 0; j < canty; j++) {
                estado = matriz[i][j];
                switch (estado) {
                    case -1: //tiene origen asignado
                        setOrigen(i, j, boton[i][j]); //se coloca como origen
                        break;
                    case -2: //tiene destino asignado
                        setDestino(i, j, boton[i][j]);
                        break;
                    case 0: //esta libre
                        liberarCasilla(i, j, boton[i][j]);
                        break;
                    case 1:
                        setObstaculo(i, j, boton[i][j]); //es obstaculo
                        break;
                }
            }
        }

    }
   
    public void addListeners() {
        for (int i = 0; i < cantx; i++) {
            for (int j = 0; j < canty; j++) {
                boton[i][j].addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent evt) {                        
                        
                        JButton evento = (JButton) evt.getSource();
                        //System.out.println("apretado el boton " + evento.getActionCommand());
                        String[] arrayPos = evento.getName().split(",");

                        int x = Integer.valueOf(arrayPos[0]);
                        int y = Integer.valueOf(arrayPos[1]);
                        System.out.println("pos seleccionada:" + x + "," + y);
                        
                        int estado = matriz[x][y];
                        switch (estado) {
                            case -1: //tiene origen asignado
                                liberarCasilla(x, y, evento);
                                origen = false;
                                break;
                            case -2: //tiene destino asignado
                                liberarCasilla(x, y, evento);
                                destino = false;
                                break;
                            case 0: //esta libre
                                if (!origen) {
                                    setOrigen(x, y, evento); //se coloca como origen
                                } else if (!destino) {
                                    setDestino(x, y, evento); //se coloca como destino
                                } else {
                                    setObstaculo(x, y, evento); //se pone obstaculo
                                }
                                break;
                            case 1:
                                liberarCasilla(x, y, evento); //era obstaculo, pero se quita
                                break;

                        }
                        setMensaje();
                    }
                });
            }
        }
    }
    
    private void setOrigen(int x, int y, JButton b) {
        matriz[x][y] = -1; // origen
        b.setBackground(java.awt.Color.white);
        b.setText("ORIGEN");
        origen = true;
        pi[0] = x;
        pi[1] = y;
    }

    private void setDestino(int x, int y, JButton b) {
        matriz[x][y] = -2; // destino
        b.setBackground(java.awt.Color.white);
        b.setText("DESTINO");
        destino = true;
        pf[0] = x;
        pf[1] = y;
    }

    private void setObstaculo(int x, int y, JButton b) {
        matriz[x][y] = 1; // obstaculo
        b.setBackground(java.awt.Color.gray);
    }
    
    private void liberarCasilla(int x, int y, JButton b) {
        matriz[x][y] = 0; // libre
        b.setBackground(java.awt.Color.lightGray);
        b.setText(null);
    }
    
    public void setParametros(int poblacion, int seleccion, int cruce, int reemplazo, int generaciones, int criterio) {
        this.setPoblacion_inicial(poblacion);
        this.setSeleccion_padres(seleccion);
        this.setTipo_cruce(cruce);
        this.setTipo_reemplazo(reemplazo);
        this.setCriterio_fin(criterio);
        this.setGeneraciones(generaciones);

    }
    public void setMensaje(){
        if(!origen)this.jLabel1.setText("Click: coloca ORIGEN");
        else if(!destino)this.jLabel1.setText("Click: coloca DESTINO");
        else this.jLabel1.setText("Click: coloca OBSTACULO");
        this.btnResolver.setEnabled(destino&&origen);
    }
    

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(principal.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(principal.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(principal.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(principal.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new principal().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenuItem aboutMenuItem;
    private javax.swing.JButton btnCargarGrid;
    private javax.swing.JButton btnDatosEjecucion;
    private javax.swing.JButton btnParametros;
    private javax.swing.JButton btnResolver;
    private javax.swing.JMenuItem contentsMenuItem;
    private javax.swing.JMenuItem exitMenuItem;
    private javax.swing.JMenu fileMenu;
    private javax.swing.JMenu helpMenu;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JMenuBar menuBar;
    // End of variables declaration//GEN-END:variables

    /**
     * @return the poblacion_inicial
     */
    public int getPoblacion_inicial() {
        return poblacion_inicial;
    }

    /**
     * @return the seleccion_padres
     */
    public int getSeleccion_padres() {
        return seleccion_padres;
    }

    /**
     * @return the tipo_cruce
     */
    public int getTipo_cruce() {
        return tipo_cruce;
    }

    /**
     * @return the tipo_reemplazo
     */
    public int getTipo_reemplazo() {
        return tipo_reemplazo;
    }

    /**
     * @return the criterio_fin
     */
    public int getCriterio_fin() {
        return criterio_fin;
    }

    /**
     * @return the generaciones
     */
    public int getGeneraciones() {
        return generaciones;
    }

    /**
     * @param poblacion_inicial the poblacion_inicial to set
     */
    public void setPoblacion_inicial(int poblacion_inicial) {
        this.poblacion_inicial = poblacion_inicial;
    }

    /**
     * @param seleccion_padres the seleccion_padres to set
     */
    public void setSeleccion_padres(int seleccion_padres) {
        this.seleccion_padres = seleccion_padres;
    }

    /**
     * @param tipo_cruce the tipo_cruce to set
     */
    public void setTipo_cruce(int tipo_cruce) {
        this.tipo_cruce = tipo_cruce;
    }

    /**
     * @param tipo_reemplazo the tipo_reemplazo to set
     */
    public void setTipo_reemplazo(int tipo_reemplazo) {
        this.tipo_reemplazo = tipo_reemplazo;
    }

    /**
     * @param criterio_fin the criterio_fin to set
     */
    public void setCriterio_fin(int criterio_fin) {
        this.criterio_fin = criterio_fin;
    }

    /**
     * @param generaciones the generaciones to set
     */
    public void setGeneraciones(int generaciones) {
        this.generaciones = generaciones;
    }
}
